package com.tarena.lbs.user.service.impl;



import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.github.pagehelper.PageInfo;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.model.Result;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.common.principle.UserPrinciple;
import com.tarena.lbs.common.utils.AuthenticationContextUtils;
import com.tarena.lbs.user.api.pojo.dto.AdminDto;
import com.tarena.lbs.user.dao.repository.AdminRepository;
import com.tarena.lbs.user.pojo.param.AdminParam;
import com.tarena.lbs.user.pojo.po.AdminPO;
import com.tarena.lbs.user.pojo.query.AdminQuery;
import com.tarena.lbs.user.pojo.vo.AdminVO;
import com.tarena.lbs.user.service.AdminService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;




@Service
@Slf4j
public class AdminServiceImpl implements AdminService {

    @Autowired
    private AdminRepository adminRepository;


    @Override
    public AdminVO detail() throws BusinessException {
        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
        log.info("userPrinciple:{}", userPrinciple);
        //断言异常
        Asserts.isTrue(userPrinciple == null, new BusinessException("-2", "认证解析错误"));
        Integer id = userPrinciple.getId();
        //2.读取数据库po
        AdminPO po = adminRepository.getAdminById(id);
        //3.转化成vo VO就是PO的复制改名 属性几乎一模一样的
        AdminVO vo = null;
        if (po != null) {
            vo = new AdminVO();
            //密码最好设置成空
            BeanUtils.copyProperties(po, vo);
        }
        return vo;
    }

    @Override
    public AdminDto detail(Integer id){
        AdminPO adminPO = adminRepository.getAdminById(id);
        AdminDto dto = null;
        if (adminPO != null){
            dto = new AdminDto();
            BeanUtils.copyProperties(adminPO,dto);
        }
        return dto;
    }

    @Override
    public PageResult<AdminVO> pageList(AdminQuery query) {
        // 创建一个新的分页结果对象，用于存储最终的分页查询结果
        PageResult<AdminVO> voPage = new PageResult<>();
        //total objects pageNo pageSize totalPage
        // 调用 adminRepository 的 gePages 方法进行分页查询，获取包含管理员持久化对象的分页信息
        PageInfo<AdminPO> pageInfo = adminRepository.pagesList(query);
        //pageNo pageSize total
        // 将分页信息中的页码设置到分页结果对象中
        voPage.setPageNo(pageInfo.getPageNum());
        // 将分页信息中的每页数量设置到分页结果对象中
        voPage.setPageSize(pageInfo.getPageSize());
        // 将分页信息中的总记录数设置到分页结果对象中
        voPage.setTotal(pageInfo.getTotal());
        // 声明一个存储管理员视图对象的列表
        List<AdminVO> vos = null;
        // 从分页信息中获取管理员持久化对象列表
        List<AdminPO> pos = pageInfo.getList();
        // 判断持久化对象列表是否不为空
        if (CollectionUtils.isNotEmpty(pos)){
            vos=pos.stream().map(po->{
                AdminVO vo = new AdminVO();
                BeanUtils.copyProperties(po,vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPage.setObjects(vos);
        return voPage;
    }

    @Override
    public void save(AdminParam param) throws BusinessException {

        // 1. 参数验证
        Asserts.isTrue(param == null, new BusinessException("-1", "参数不能为空"));
        Asserts.isTrue(StringUtils.isEmpty(param.getAccountPhone()), new BusinessException("-1", "手机号不能为空"));
        Asserts.isTrue(StringUtils.isEmpty(param.getAccountPassword()), new BusinessException("-1", "密码不能为空"));
        Asserts.isTrue(StringUtils.isEmpty(param.getNickname()), new BusinessException("-1", "用户名称不能为空"));
        Asserts.isTrue(StringUtils.isEmpty(param.getEmail()), new BusinessException("-1", "电子邮箱不能为空"));

        // 2. 验证账号类型为商家时，businessId不能为空
        if (param.getAccountType() != null && param.getAccountType() == 1) {
            Asserts.isTrue(param.getBusinessId() == null, new BusinessException("-1", "商家账号的商家ID不能为空"));
        }

        // 3. 检查手机号是否已存在
        AdminPO existingAdmin = adminRepository.getAdminByPhone(param.getAccountPhone());
        Asserts.isTrue(existingAdmin != null, new BusinessException("-1", "该手机号已被注册"));

        // 4. 将AdminParam转换为AdminPO
        AdminPO adminPO = new AdminPO();
        BeanUtils.copyProperties(param, adminPO);

        // 5. 设置创建时间
        adminPO.setCreateTime(new Date());

        // 6. 调用Repository保存数据
        adminRepository.save(adminPO);
    }

    @Override
    public void update(AdminParam param) throws BusinessException {
        // 1. 参数验证
        Asserts.isTrue(param == null, new BusinessException("-1", "参数不能为空"));
        Asserts.isTrue(param.getId() == null || param.getId() <= 0, new BusinessException("-1", "ID不能为空"));
        Asserts.isTrue(StringUtils.isEmpty(param.getAccountPhone()), new BusinessException("-1", "手机号不能为空"));
        Asserts.isTrue(StringUtils.isEmpty(param.getNickname()), new BusinessException("-1", "用户名称不能为空"));
        Asserts.isTrue(StringUtils.isEmpty(param.getEmail()), new BusinessException("-1", "电子邮箱不能为空"));
        Asserts.isTrue(param.getAccountType() == null || (param.getAccountType() != 0 && param.getAccountType() != 1),
                new BusinessException("-1", "账号类型无效（0：平台管理员，1：商家管理员）"));

        // 2. 验证账号类型为商家时，businessId不能为空
        if (param.getAccountType() == 1) {
            Asserts.isTrue(param.getBusinessId() != null, new BusinessException("-1", "商家账号的商家ID不能为空"));
        }

        // 3. 检查管理员是否存在
        AdminPO existingAdmin = adminRepository.getAdminById(param.getId());
        Asserts.isTrue(existingAdmin == null, new BusinessException("-1", "管理员不存在或已被删除"));

        // 4. 检查手机号是否已被其他账号使用
        AdminPO phoneAdmin = adminRepository.getAdminByPhone(param.getAccountPhone());
        Asserts.isTrue(phoneAdmin != null && !phoneAdmin.getId().equals(param.getId()),
                new BusinessException("-1", "该手机号已被其他账号注册"));

        // 5. 将AdminParam转换为AdminPO
        AdminPO adminPO = new AdminPO();
        BeanUtils.copyProperties(param, adminPO);

        // 6. 设置更新时间
        adminPO.setUpdateTime(new Date());

        // 7. 如果是平台管理员，清空businessId
        if (param.getAccountType() == 0) {
            adminPO.setBusinessId(null);
        }

        // 8. 调用Repository更新数据
        adminRepository.update(adminPO);

        log.info("管理员账号更新成功，ID:{}", param.getId());
    }

    @Override
    public Result<Void> deleteAdmin(Integer id) {
        if (id == null || id <= 0){
            return Result.fail("-1", "ID不能为空");
        }

       //检查文章是否存在
        AdminPO adminPO = adminRepository.getAdminById(id);
        if (adminPO == null) {
            return Result.fail("-1", "ID不存在");
        }

        //执行假删除
        int rows = adminRepository.deleteAdmin(id);
        if (rows <= 0){
            return Result.fail("-1", "删除失败");
        }
        return Result.success();
    }



    @Override
    public void updateStatus(Integer id, Integer status) {

    }

    @Override
    public void assignRole(Integer id, Integer accountType, Integer businessId) throws BusinessException {
        // 参数校验
        Asserts.isTrue(id == null || id <= 0, new BusinessException("-1", "ID不能为空"));
        Asserts.isTrue(accountType == null || (accountType != 0 && accountType != 1),
                new BusinessException("-1", "角色类型无效（0：平台管理员，1：商家管理员）"));

        // 如果是商家管理员，businessId不能为空
        if (accountType == 1) {
            Asserts.isTrue(businessId == null, new BusinessException("-1", "商家管理员必须关联商家ID"));
        }


        // 检查管理员是否存在
        AdminPO adminPO = adminRepository.getAdminById(id);
        Asserts.isTrue(adminPO == null, new BusinessException("-1", "管理员不存在或已被删除"));

        // 调用Repository层执行角色分配
        adminRepository.assignRole(id, accountType, businessId);
        log.info("管理员角色分配成功，ID:{}, 新角色类型:{}", id, accountType);
    }


    @Override
    public void resetPassword(Integer id) throws BusinessException {
        // 参数校验已在Controller层完成

        // 调用Repository层执行密码重置
        adminRepository.resetPassword(id);
        log.info("管理员密码重置成功，ID:{}", id);
    }

}